﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace MMS.Respository
{

    public class BaseRespository<TEntity>:IRespository.IBaseRespository<TEntity> where TEntity:class
    {
        DbContext db = EFFatory.GetEFContext();
        DbSet<TEntity> dbSet = null;
        public BaseRespository()
        {
            db.Configuration.ValidateOnSaveEnabled = false;
            dbSet = db.Set<TEntity>();
        }

        public TEntity Single(Expression<Func<TEntity,bool>> where)
        {
            return dbSet.SingleOrDefault(where);
        }




        public void Add(TEntity Model)
        {
            dbSet.Add(Model);
        }

        public void Remove(TEntity Model)
        {
            dbSet.Attach(Model);
            dbSet.Remove(Model);
        }

        public void RemoveBy(Expression<Func<TEntity, bool>> where)
        {
            var list = dbSet.Where(where);
            foreach (var item in list)
            {
                dbSet.Remove(item);
            }
        }

        public void Modify(TEntity Model, params string[] updateProperties)
        {
           
            DbEntityEntry<TEntity> entry = db.Entry<TEntity>(Model);
            entry.State = System.Data.EntityState.Unchanged;
            foreach (var propertyName in updateProperties)
            {
                entry.Property(propertyName).IsModified = true;
            }
        }

        public void ModifyBy(Expression<Func<TEntity, bool>> where, string[] propertyNames, object[] values)
        {
            if (propertyNames == null || values == null)
                throw new ArgumentException("属性名和属性值数组都不能为Null~~！");
            var list = dbSet.Where(where);
            Type type = typeof(TEntity);
            foreach(var item in list)
            {
                for (int i = 0; i < propertyNames.Length; i++)
                {
                    PropertyInfo pi = type.GetProperty(propertyNames[i]);
                    pi.SetValue(item, values[i], null);
                }
            }
        }

        public IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> where)
        {
            return dbSet.AsNoTracking().Where(where);
        }

        public IQueryable<TEntity> Where<TKey>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TKey>> orderBy, bool isAsc = true)
        {
            if (isAsc)
                return dbSet.AsNoTracking().Where(where).OrderBy(orderBy);
            else
                return dbSet.AsNoTracking().Where(where).OrderByDescending(orderBy);
        }

        public Model.FormatModel.PageData<TEntity> WherePaged<TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TKey>> orderBy, bool isAsc = true)
        {
            var dbSetWhered = dbSet.AsNoTracking().Where(where);
            IOrderedQueryable<TEntity> orderWhere = null;
            if (isAsc)
                orderWhere = dbSetWhered.OrderBy(orderBy);
            else
                orderWhere = dbSetWhered.OrderByDescending(orderBy);
            Model.FormatModel.PageData<TEntity> pageData = new Model.FormatModel.PageData<TEntity>();
            pageData.rows = orderWhere.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            pageData.total = dbSetWhered.Count();

            return pageData;
        }

        public Model.FormatModel.PageData<TEntity> WherePaged<TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TKey>> orderBy, bool isAsc = true, params string[] includeNames)
        {
            
            DbQuery<TEntity> dbQuery = dbSet;
            foreach (string includeN in includeNames)
            {
                dbQuery = dbQuery.Include(includeN);
            }

            var dbSetWhered = dbQuery.AsNoTracking().Where(where);
            IOrderedQueryable<TEntity> orderWhere = null;
            if (isAsc)
                orderWhere = dbSetWhered.OrderBy(orderBy);
            else
                orderWhere = dbSetWhered.OrderByDescending(orderBy);
           
            Model.FormatModel.PageData<TEntity> pageData = new Model.FormatModel.PageData<TEntity>();
            pageData.rows = orderWhere.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            pageData.total = dbSetWhered.Count();

            return pageData;
        }

        public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters)
        {
            return db.Database.SqlQuery<TElement>(sql, parameters);
        }
        public IEnumerable SqlQuery(Type elementType, string sql, params object[] parameters)
        {
            return db.Database.SqlQuery(elementType, sql, parameters);
        }
    }
}
